package com.ls.bpmn.controller;


import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.ls.bpmn.entity.CategoryDefinition;
import com.ls.bpmn.service.ICategoryDefinitionService;
import com.ls.bpmn.service.IDefinitionService;
import com.ls.common.Constast;
import com.ls.common.DataGridView;
import com.ls.common.PageModel;
import com.ls.common.ResultObj;

import org.apache.commons.io.IOUtils;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.repository.DeploymentBuilder;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.yaml.snakeyaml.util.UriEncoder;


import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

@RestController
@RequestMapping("/definition")
public class DefinitionController {
    private static final Logger log = LoggerFactory.getLogger(DefinitionController.class);

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private IDefinitionService definitionService;

    @Autowired
    private ICategoryDefinitionService categoryDefinitionService;

    @GetMapping("/list")
    public DataGridView list(PageModel pageModel, @RequestParam(required = false) Integer categoryId) {

        return definitionService.list(pageModel, categoryId);
    }

    @PostMapping(value = "/deploy", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResultObj deploy(
            @RequestPart("file") MultipartFile file,
            @RequestParam("categoryId") Integer categoryId) {
        try {
            //文件名称获取
            String name = file.getOriginalFilename();
            //流程定义部署
            DeploymentBuilder builder = this.repositoryService.
                    createDeployment().addInputStream(name, file.getInputStream()) ;
            List<ProcessDefinition> ds = builder.deployWithResult().getDeployedProcessDefinitions ();

            ProcessDefinition definition = ds.get(0);
            //查询部署的流程定义文件是否已关联分类
            CategoryDefinition bcp = categoryDefinitionService.getOne(new QueryWrapper<CategoryDefinition>()
                    .eq("definition_key", definition.getKey()));
            if (ObjectUtil.isNotEmpty(bcp) && !bcp.getCategoryId().equals(categoryId)){
                //流程定义已关联分类，不能再部署
                repositoryService.deleteProcessDefinition(definition.getId());
                throw new Exception("该流程图已关联分类，操作失败!");
            }else {
                //流程分类关联
                CategoryDefinition procDefCategory = new CategoryDefinition();
                procDefCategory.setDefinitionKey(definition.getKey());
                procDefCategory.setCategoryId(categoryId);
                procDefCategory.setDefinitionId(definition.getId());
                categoryDefinitionService.saveOrUpdate(procDefCategory);

                return new ResultObj(Constast.OK, "部署成功", definition.getId());
            }
        } catch (Exception e) {
            log.error("部署失败: {}", e.getMessage());
            return new ResultObj(Constast.ERROR, "部署失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}/data")
    public void download(@PathVariable String id, HttpServletResponse response) {
        try {
            ProcessDefinition definition = this.repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
            InputStream is = repositoryService.getProcessModel(id);
            String name = definition.getKey() + "_v" + definition.getVersion() + ".bpmn";
            response.addHeader("Content-Disposition", "attachment;filename=" + UriEncoder.encode(name));
            response.setContentType("application/xml;charset=UT-8");
            response.setCharacterEncoding("UTF-8");
            response.addHeader("Content-Length", is.available() + "");
            OutputStream os = response.getOutputStream();
            IOUtils.copy(is, os);
            os.flush();
            os.close();
        } catch (Exception e) {
            log.error("下载流程文件出错，{}", e);
        }
    }

    @PostMapping("/delete/{id}")
    public ResultObj delete(@PathVariable String id) {
        try {
            ProcessDefinition p = repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
            if(ObjectUtil.isNotEmpty(p)){
                categoryDefinitionService.remove(
                        new QueryWrapper<CategoryDefinition>().eq("definiton_id",p.getId()));
                repositoryService.deleteProcessDefinition(id, true);
            }
            return new ResultObj(Constast.OK, "删除成功", id);
        } catch (Exception e) {
            log.error("删除流程定义失败: {}", e.getMessage());
            return new ResultObj(Constast.ERROR, "删除失败", null);
        }
    }

}